package com.hsteach.service.equipment;

import com.google.common.collect.Lists;
import com.hsteach.common.config.App;
import com.hsteach.common.config.AppConfig;
import com.hsteach.common.core.domain.model.AuthInfo;
import com.hsteach.common.exception.ServiceException;
import com.hsteach.common.utils.DateUtils;
import com.hsteach.common.utils.SecurityUtils;
import com.hsteach.common.utils.StringUtils;
import com.hsteach.dao.domain.equipment.EquipmentRepair;
import com.hsteach.dao.domain.equipment.EquipmentRepairConfig;
import com.hsteach.dao.domain.equipment.EquipmentRepairFiles;
import com.hsteach.dao.mapper.equipment.EquipmentRepairConfigMapper;
import com.hsteach.dao.mapper.equipment.EquipmentRepairFilesMapper;
import com.hsteach.dao.mapper.equipment.EquipmentRepairMapper;
import com.hsteach.dao.mapper.equipment.EquipmentRepairResultMapper;
import com.hsteach.enums.BooleanEnum;
import com.hsteach.enums.MsgTypeEnum;
import com.hsteach.framework.feign.client.xgk.dto.ret.GetTeacherRet;
import com.hsteach.service.third.MessageService;
import com.hsteach.service.third.XgkService;
import com.hsteach.util.ConstantCode;
import com.hsteach.web.controller.equipment.dto.AssignDto;
import com.hsteach.web.controller.equipment.dto.EquipmentPublicDto;
import com.hsteach.web.controller.equipment.dto.EquipmentRepairDto;
import com.hsteach.web.controller.equipment.dto.PersonVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 设备报修服务层
 */

@Slf4j
@Service
public class EquipmentRepairService {

    @Autowired
    private EquipmentRepairMapper equipmentRepairMapper;

    @Autowired
    private EquipmentRepairFilesMapper equipmentRepairFilesMapper;

    @Autowired
    private EquipmentRepairResultMapper equipmentRepairResultMapper;

    @Autowired
    private EquipmentRepairConfigMapper equipmentRepairConfigMapper;

    @Autowired
    private MessageService messageService;

    @Autowired
    private XgkService xgkService;

    @Autowired
    private AppConfig appConfig;

    private static final String EQUIPMENT_REPAIR = "equipmentRepair";
    private static final String EQUIPMENT_REPAIR_FILES = "equipmentRepairFiles";
    private static final String EQUIPMENT_REPAIR_RESULT_FILES = "equipmentRepairResultFiles";
    private static final String EQUIPMENT_REPAIR_RESULT = "equipmentRepairResult";


    /**
     * 查询设备报修列表
     *
     * @param dto
     * @return
     */
    public List<EquipmentRepair> queryList(EquipmentPublicDto dto) {
        EquipmentPublicDto query = new EquipmentPublicDto();
        query.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
        query.setStatus(1);
        List<EquipmentRepairConfig> equipmentRepairConfigs = equipmentRepairConfigMapper.queryListByStatus(query);
        // 初始配置
        if (CollectionUtils.isEmpty(equipmentRepairConfigs)) {
            Lists.newArrayList("其它维修","实验室设备维修","空调和风扇等电器维修","桌椅和门窗等器具维修","电子产品和网络维修","水电维修").stream().forEach(e -> {
                EquipmentRepairConfig config = new EquipmentRepairConfig();
                config.setStatus(BooleanEnum.FALSE.getCode());
                config.setDelStatus(BooleanEnum.TRUE.getCode());
                config.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
                config.setRepairType(e);
                equipmentRepairConfigMapper.insert(config);
            });
        }
        dto.setPersonId(SecurityUtils.getAuthInfo().getPersonId());
        dto.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
        return equipmentRepairMapper.queryList(dto);
    }

    /**
     * 查询设备报修详情
     *
     * @param id
     * @return
     */
    public Map<String, Object> queryDetail(Long id) {
        Map<String, Object> returnMap = new HashMap();
        EquipmentRepair equipmentRepair = equipmentRepairMapper.queryDetail(id);
        if (ObjectUtils.isEmpty(equipmentRepair)) {
            throw new ServiceException("未获取到报修信息!");
        }
        List<GetTeacherRet> teachers = xgkService.getTeachers(SecurityUtils.getAuthInfo().getId());
        Map<String, GetTeacherRet> teacherMap = teachers.stream().collect(Collectors.toMap(GetTeacherRet::getPersonId, teacher -> teacher, (v1, v2) -> v2));
        GetTeacherRet teacherRet = teacherMap.get(equipmentRepair.getRepairPersonId());
        equipmentRepair.setRepairPersonMobile(ObjectUtils.isEmpty(teacherRet)?"": teacherRet.getPhone());
        List<PersonVo> ret = new ArrayList<>();
        if (StringUtils.isEmpty(equipmentRepair.getRepairPerson())){
            EquipmentPublicDto query = new EquipmentPublicDto();
            query.setDelStatus(1);
//        query.setStatus(1);
            query.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
            query.setTypes(Lists.newArrayList(equipmentRepair.getRepairType()));
            List<EquipmentRepairConfig> configs = equipmentRepairConfigMapper.queryListByType(query);
            ret = configs.stream().map(j -> {
                PersonVo vo = new PersonVo();
                vo.setPersonId(j.getPersonId());
                vo.setPersonName(j.getPersonName());
                vo.setPersonMobile(j.getPersonMobile());
                if (teacherMap.containsKey(equipmentRepair.getPersonId())) {
                    GetTeacherRet teacher = teacherMap.get(j.getPersonId());
                    vo.setPersonMobile(ObjectUtils.isEmpty(teacher)?"": teacher.getPhone());
                }
                return vo;
            }).collect(Collectors.toList());
        }else {
            GetTeacherRet teacher = teacherMap.getOrDefault(equipmentRepair.getRepairPerson(),new GetTeacherRet());
            PersonVo vo = new PersonVo();
            vo.setPersonId(teacher.getPersonId());
            vo.setPersonName(teacher.getName());
            vo.setPersonMobile(teacher.getPhone());
            ret.add(vo);
        }
        equipmentRepair.setPersons(ret);
        returnMap.put(EQUIPMENT_REPAIR, equipmentRepair);
        //查询报修详情的附件
        List<EquipmentRepairFiles> fileList = equipmentRepairFilesMapper.queryFileListByRepairId(id,ConstantCode.REPAIR_INFO);
        returnMap.put(EQUIPMENT_REPAIR_FILES, fileList);

        //判断此此报修是否已完成维修，如已完成，需要查询维修详情
        if (ConstantCode.ONE == equipmentRepair.getStatus()) {
            List<Map> resultList = equipmentRepairResultMapper.queryResultListByRepairId(id);
            if (resultList.size() == ConstantCode.ZERO){
                throw new ServiceException("未获取到维修信息!");
            }
            for (Map resultMap : resultList) {
                if (resultMap.containsKey("create_time")) {
                    LocalDateTime createTime = (LocalDateTime) resultMap.get("create_time");
                    DateTimeFormatter fomatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    resultMap.put("create_time", fomatter.format(createTime));
                }
                //查询维修详情的附件
                resultMap.put(EQUIPMENT_REPAIR_RESULT_FILES,equipmentRepairFilesMapper.queryFileListByRepairId((Long)resultMap.get("id"),ConstantCode.RESULT_INFO));
            }
            returnMap.put(EQUIPMENT_REPAIR_RESULT, resultList);
        }
        return returnMap;
    }


    /**
     * 新增报修信息
     * @param equipmentRepairDto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Long add(EquipmentRepairDto equipmentRepairDto) {
        EquipmentRepair equipmentRepair = new EquipmentRepair();
        BeanUtils.copyProperties(equipmentRepairDto, equipmentRepair);
        equipmentRepair.setPersonId(SecurityUtils.getAuthInfo().getPersonId());
        equipmentRepair.setPersonName(SecurityUtils.getAuthInfo().getName());
        equipmentRepair.setPersonMobile(SecurityUtils.getAuthInfo().getMobile());
        equipmentRepair.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
        EquipmentPublicDto dto = new EquipmentPublicDto();
        dto.setRepairType(equipmentRepairDto.getRepairType());
        List<EquipmentRepairConfig> configList = equipmentRepairConfigMapper.queryListByType(dto);
        if (configList.size() == 1){
            equipmentRepair.setRepairPerson(configList.get(0).getPersonId());
        }
        Long i = equipmentRepairMapper.insert(equipmentRepair);
        if (i != 1){
            throw new ServiceException("保存保修信息失败!");
        }
        //保存保修附件
        if(!ObjectUtils.isEmpty(equipmentRepairDto.getFiles()) && equipmentRepairDto.getFiles().size() > 0){
            EquipmentRepairFiles equipmentRepairFiles = new EquipmentRepairFiles();
            equipmentRepairDto.getFiles().forEach(fileVo -> {
                equipmentRepairFiles.setRepairId(equipmentRepair.getId());
                equipmentRepairFiles.setUrl(fileVo.getFileUrl());
                //类型 1图片 2视频 3文件
                equipmentRepairFiles.setFileType(fileVo.getFileType());
                //附件属于报修（repairInfo）/ 维修（resultInfo）
                equipmentRepairFiles.setBelongTo(ConstantCode.REPAIR_INFO);
                equipmentRepairFilesMapper.insert(equipmentRepairFiles);
            });
        }

        //---------------------发送消息通知-------------------------
        //构建消息内容
//        String msg = SecurityUtils.getAuthInfo().getName() + "于" + DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", new Date())
//                + "申请了设备报修，设备地点在" + equipmentRepairDto.getBuildingLocationName() + equipmentRepairDto.getRoomLocationName()
//                + "，设备问题为：" + equipmentRepairDto.getRepairDesc();

        String msg = equipmentRepairDto.getBuildingLocationName() + (equipmentRepairDto.getRoomLocationName() == null ? "":equipmentRepairDto.getRoomLocationName()) + "有" + equipmentRepairDto.getRepairType() + "待维修";

        //根据维修类型查询接收消息通知的人员
        List<String> personList = equipmentRepairConfigMapper.queryListByRepairType(equipmentRepairDto.getRepairType());
        sendMsg(personList, msg, equipmentRepair.getId());
        return equipmentRepair.getId();
    }

    private void sendMsg(List<String> toPersonIds, String msg, Long id) {
        try {
            AuthInfo authInfo = SecurityUtils.getAuthInfo();
            String appId = authInfo.getAppId();
            App app = appConfig.getConfig().get(appId);
            if (app == null) {
                return;
            }
            String params = "&msgId=" + id;
//            String encode = URLEncoder.encode(params, "UTF-8");
            String url = app.getRedirectUrl() + params;
            String content = "<p>" + msg + "<a href=\"" + url + "\">跳转进应用</a></p>";
            List<GetTeacherRet> teachers = xgkService.getTeachers(SecurityUtils.getAuthInfo().getId());
            Map<String, String> teacherMap = teachers.stream().filter(e -> e.getT_userID() != null).collect(Collectors.toMap(GetTeacherRet::getPersonId, GetTeacherRet::getT_userID, (v1, v2) -> v2));
            List<String> tPersonId = Lists.newArrayList();
            for (String personId: toPersonIds) {
                if (teacherMap.containsKey(personId)) {
                    tPersonId.add(teacherMap.get(personId));
//                    messageService.addTodothings(msg, teacherMap.get(personId), SecurityUtils.getAuthInfo().getOrganizeId(), "/test", MsgTypeEnum.REPAIR_NOTIFY);
                }
            }
            if (CollectionUtils.isNotEmpty(tPersonId)) {
                messageService.sendMsg(content, tPersonId, MsgTypeEnum.REPAIR_NOTIFY, msg);
            }
        } catch (Exception e) {
            log.error("EquipmentRepairService sendMsg error", e);
        }
    }

    public int assign(AssignDto dto) {
        EquipmentRepair equipmentRepair = equipmentRepairMapper.queryDetail(dto.getId());
        if (equipmentRepair == null) {
            throw new ServiceException("报修不存在");
        }
        if (equipmentRepair.getRepairPerson() != null) {
            throw new ServiceException("该报修已指派人员");
        }
        EquipmentRepair update = new EquipmentRepair();
        update.setId(dto.getId());
        update.setRepairPerson(dto.getPersonId());
        return equipmentRepairMapper.update(update);
    }
}
